package io.mft.datasource.db.executor;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.db.sql.Condition;
import cn.hutool.db.sql.Condition.LikeType;
import io.mft.api.domain.Api;
import io.mft.api.domain.DataAccessRegulation;
import io.mft.api.domain.ExecutingResource;
import io.mft.api.domain.InputParameter;
import io.mft.api.domain.builder.SqlIdBuilder;
import io.mft.commons.function.ExecuteReturn;
import io.mft.commons.function.RequestValue;
import io.mft.commons.function.datasource.DatasourceInvokeType;
import io.mft.datasource.db.accessor.bean.DAContext;
import io.mft.datasource.db.accessor.bean.DARequest;
import io.mft.datasource.db.accessor.bean.DAResponse;
import io.mft.datasource.db.accessor.bean.DbContextValue;
import io.mft.dev.base.BaseFunctionOfDataAccess;
import io.mft.plugin.PluginContext;

/**
 * 数据库分页查询处理器
 * 
 * @说明：TODO
 * @类型名称：DbProcessExecutor
 * @创建者: 胡常建
 * @创建时间: 2021年1月29日 下午2:33:36
 * @修改者: 胡常建
 * @修改时间: 2021年1月29日 下午2:33:36
 */
public abstract class DbProcessExecutor extends BaseFunctionOfDataAccess{
	Logger logger=LoggerFactory.getLogger(DbProcessExecutor.class);
	private static final String OPERATOR_LIKE = "LIKE";
	private static final String OPERATOR_IN = "IN";
	private static final String OPERATOR_IS = "IS";
	private static final String OPERATOR_IS_NOT = "IS NOT";
	private static final String OPERATOR_BETWEEN = "BETWEEN";
	@Override
	public ExecuteReturn doExecute(PluginContext<ExecutingResource<DataAccessRegulation>> context) {
		ExecutingResource<DataAccessRegulation> executingResource=context.getValue();
		String sqlId=SqlIdBuilder.build(executingResource.getApi(), executingResource.getExecutingRegulation());
		DbContextValue contextValue = DbContextValue.builder()
				.datasourceId(executingResource.getExecutingRegulation().getDatasource().getKey())
				.scriptKey(sqlId).api(executingResource.getApi()).dataAccessRegulation(executingResource.getExecutingRegulation()).build();
		ExecuteReturn executeReturn=ExecuteReturn.builder().build();
		RequestValue requestValue=new RequestValue();
		requestValue.initValue(context.getRequest().getRequestValue());
		executeReturn=invoke(requestValue,context, executingResource, contextValue);
		return executeReturn;
	}
	
	private ExecuteReturn invoke(RequestValue requestValue,PluginContext<ExecutingResource<DataAccessRegulation>> context,ExecutingResource<DataAccessRegulation> executingResource,DbContextValue contextValue) {
		DatasourceInvokeType regulationType=executingResource.getExecutingRegulation().getType();
		if (regulationType==DatasourceInvokeType.sqlfunction||regulationType==DatasourceInvokeType.sqlprocedure) {
			executingResource.getApi().getInput().getInputParameters().forEach(input -> {
				if (!ObjectUtil.isNull(input.getDataType())) {
					String key = input.getActualKey() + "." + "dataType";
					requestValue.set(key, input.getDataType().name());
				}
			});			
		}
		fixSQLConditionRequestValue(executingResource.getApi(), requestValue);
		DARequest daRequest = new DARequest(requestValue);
		DAResponse daResponse=new DAResponse(context.getResponse());
		daResponse.setDsKeyNamespace(context.getResponse().getDsKeyNamespace());
		DAContext<DbContextValue> daRequestContext = new DAContext<DbContextValue>(contextValue, daRequest,daResponse);
		logger.debug("功能号:{}->>>数据库执行->>>参数:{}",executingResource.getApi().getKey(),requestValue);
		ExecuteReturn executeReturn = invokeDbAccessor(executingResource.getExecutingRegulation(),daRequestContext);
		return executeReturn;
	}
	
	private void fixSQLConditionRequestValue(Api api,RequestValue data) {
		List<InputParameter> inputParameters=api.getInput().getInputParameters();
		for (InputParameter inputParameter : inputParameters) {
			if (ObjectUtil.isNotEmpty(inputParameter.getCondition())&&ObjectUtil.isNotEmpty(inputParameter.getConditionType())) {
				if (OPERATOR_LIKE.equals(inputParameter.getCondition())) {
					Condition condition=new Condition(inputParameter.getActualKey(),data.getStr(inputParameter.getActualKey()), LikeType.valueOf(inputParameter.getConditionType()));
					data.set(inputParameter.getActualKey(), condition);
				}else if (OPERATOR_BETWEEN.equals(inputParameter.getCondition())) {
					
				}else if (OPERATOR_IN.equals(inputParameter.getCondition())) {
					
				}else if (OPERATOR_IS.equals(inputParameter.getCondition())) {
					
				}else if (OPERATOR_IS_NOT.equals(inputParameter.getCondition())) {
					
				}
			}
		}
	}
	/**
	 * 调用数据库访问器
	 * @说明: TODO
	 * @方法名称: invokeDbAccessor
	 * @参数 @param daRequestContext
	 * @参数 @return
	 * @返回类型 DAResponse    
	 * @创建者: 胡常建  
	 * @创建时间: 2021年2月18日 上午9:16:36
	 * @修改者: 胡常建  
	 * @修改时间: 2021年2月18日 上午9:16:36
	 */
	protected abstract ExecuteReturn invokeDbAccessor(DataAccessRegulation dataAccessRegulation,DAContext<DbContextValue> daRequestContext);
}
